﻿using System;
using System.Collections.Generic;
using Dexter.Domain.Model;
using Dexter.Logger.Contracts;
using Dexter.Scheduler;
using Dexter.Search;
using Dexter.Services;
using Dexter.Web.Utils;

namespace Dexter.Job.Publishing {
	/// <summary>
	/// The implementation of <see cref="IFrequentlyJob"/>. This job will publish the scheduled post.
	/// </summary>
	public class PublishItemJob : IFrequentlyJob {
		readonly ILogger logger;
		readonly IPostService postService;
		readonly ITraceUtils traceUtils;
		readonly IPingService pingService;
		readonly IUrlBuilder urlBuilder;
		readonly IConfigurationService configurationService;
		readonly ISearchService searchService;

		/// <summary>
		/// Initializes a new instance of the <see cref="PublishItemJob"/> class.
		/// </summary>
		/// <param name="logger">The logger.</param>
		/// <param name="postService">The post service.</param>
		/// <param name="traceUtils">The ping back track back utils.</param>
		/// <param name="pingService">The ping service.</param>
		/// <param name="urlBuilder">The URL builder.</param>
		/// <param name="configurationService">The configuration service.</param>
		/// <param name="searchService">The index service.</param>
		public PublishItemJob ( ILogger logger, IPostService postService, ITraceUtils traceUtils, IPingService pingService, IUrlBuilder urlBuilder, IConfigurationService configurationService, ISearchService searchService ) {
			this.logger = logger;
			this.searchService = searchService;
			this.configurationService = configurationService;
			this.urlBuilder = urlBuilder;
			this.pingService = pingService;
			this.traceUtils = traceUtils;
			this.postService = postService;
		}

		/// <summary>
		/// Gets a value indicating whether [auto manage session].
		/// </summary>
		/// <value><c>true</c> if [auto manage session]; otherwise, <c>false</c>.</value>
		public bool AutoManageSession {
			get { return true; }
		}

		/// <summary>
		/// Gets the name of the group.
		/// </summary>
		/// <value>The name of the group.</value>
		public string GroupName {
			get { return null; }
		}

		/// <summary>
		/// Set to <c>false</c> if the state of Job will be reused from the next startup. Otherwise <c>false</c>.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is volatile; otherwise, <c>false</c>.
		/// </value>
		public bool IsVolatile {
			get { return true; }
		}

		/// <summary>
		/// Gets the unique id.
		/// </summary>
		/// <value>The unique id.</value>
		public string UniqueId {
			get { return "{56db5b44-4937-4089-82f2-200732109958}"; }
		}

		/// <summary>
		///This method will be exececuted by the <see cref="IScheduler"/>
		/// </summary>
		/// <remarks>
		///	The execution interval depends by <see cref="ICronJob"/> or <see cref="IFrequentlyJob"/>.
		/// </remarks>
		public void Execute ( ) {
			logger.Debug ( "Executing 'PublishItemJob' started" );

			var posts = postService.GetUnpublishedForTheSpecifiedDate ( 0 , 1000 , DateTime.Today );

			if(posts.TotalCount > 0) {
				var pingSites = pingService.GetPingSites ( );
				var configuration = configurationService.Configuration;

				foreach ( var post in posts.Result ) {
					if (post == null) {
						logger.Fatal ( "Houston we have a problem!" );
						continue;
					}

					post.Publish (  );
					postService.Update ( post );

					logger.Debug ( "Updating search index." );
					searchService.IndexItem ( post );

					
					SendPingbackTrackback ( post, pingSites, configuration );
				}
			}

			logger.Debug ( "Execution 'PublishItemJob' completed" );
		}

		void SendPingbackTrackback ( Item post , IEnumerable <Uri> pingSites , SiteConfiguration configuration ) {
			foreach ( var pingSite in pingSites ) {
				var postUrl = new Uri ( urlBuilder.Post.Detail ( post ) );

				if(configuration.Tracking.EnablePingBackSend) {
					logger.DebugFormat ( "Sending pingback for{0}", postUrl );
					traceUtils.SendPingBack ( post , postUrl );
				}

				if (configuration.Tracking.EnableTrackBackSend) {
					logger.DebugFormat ( "Sending trackback for{0}", postUrl );
					traceUtils.SendTrackBack ( post, postUrl );
				}

				logger.DebugFormat ( "Sending ping for {0} to {1}" , postUrl , pingSite );
				traceUtils.Ping ( postUrl , pingSite );
			}
		}

		/// <summary>
		/// The elapsed minutes from a job execution and the next one.
		/// </summary>
		/// <value>The minutes.</value>
		public int Minutes {
			get { return 5; }
		}
	}
}
